/**
 * 自定义指令;
 */
import { Directive, forwardRef, Attribute } from '@angular/core';
import { Validator, AbstractControl, NG_VALIDATORS } from '@angular/forms';

@Directive({
  // selector: 定义指令在 HTML 代码中匹配的方式
  /* tslint-disable */
  selector: '[validateEqual][formControlName],[validateEqual][formControl],[validateEqual][ngModel]',
  // providers - 注册EqualValidator
  providers: [
    // tips: forwardRef的作：在使用构造注入时，使用尚未定义的依赖对象类型 ,参考: https://segmentfault.com/a/1190000008626276
    { provide: NG_VALIDATORS, useExisting: forwardRef(() => EqualValidatorDirective), multi: true }
  ]
})
export class EqualValidatorDirective implements Validator {
  // 在构造函数中，我们通过 @Attribute('validateEqual') 装饰器来获取 validateEqual 属性上设置的值。
  constructor(@Attribute('validateEqual') public validateEqual: string, @Attribute('reverse') public reverse: string) {}

  private get isReverse() {
    if (!this.reverse) {
      return false;
    }
    return this.reverse === 'true';
  }

  // EqualValidatorDirective类必须实现Validator接口，要求定义一个 validate() 方法;
  validate(c: AbstractControl): { [key: string]: any } {
    const v = c.value; // 获取应用该指令 控件上的值

    const e = c.root.get(this.validateEqual); // 获取进行值对比的控件

    // if (e && v !== e.value) {
    //   return {
    //     validateEqual: false
    //   };
    // }

    // 未设置reverse的值或值为false
    if (e && v !== e.value && !this.isReverse) {
      return {
        validateEqual: false
      };
    }
    // 若值相等且reverse的值为true，则删除validateEqual异常信息
    if (e && v === e.value && this.isReverse) {
      delete e.errors['validateEqual'];
      if (!Object.keys(e.errors).length) {
        e.setErrors(null);
      }
    }
    // 若值不相等且reverse的值为true，则把异常信息添加到比对的目标控件上
    if (e && v !== e.value && this.isReverse) {
      e.setErrors({ validateEqual: false });
    }
    return null;
  }
}
